package com.cyh.testcustomui;

import androidx.appcompat.app.AppCompatActivity;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.animation.DecelerateInterpolator;

/**
 * ScrollView和ListView显示不全的问题：原因是他们两个的高度模式都是：MeasureSpec.UNSPECIFIED。
 *   所以要在onMeasure中添加：
 *      高度的最大值就是int的最大值去掉前两位。
 *      int是32位， 前30位是值，后两位是模式
 *      heightMeasureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
 *      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 *
 * 默认情况下ViewGroup(如LinearLayout)不会调用onDraw方法，所以默认不会绘制内容，但是如果加了背景时，会调用onDraw方法
 * 为了不设置背景也能绘制，方法一：将onDraw方法改成dispatchDraw方法。
 *                      方法二：在构造函数中设置一个透明背景：setBackgroundColor(Color.TRANSPARENT)
 *                      方法三：在构造函数中setWillNotDraw(false);
 *
 *
 *
 * 为什么不能在子线程中更新UI
 * 在子线程中更新UI,一般会调用setText,setImageView(),就会去调用ViewRootImpl.checkThread();
 * checkThread()是用来检查线程的函数，如果当前线程更原始线程不一样，会报错。
 * 原型线程指创建View的线程，一般是主线程。
 *
 *
 * 自定义View的套路：
 *    1）自定义属性，获取自定义属性
 *    2）onMeasure()方法用于测了自己的宽高，前提是继承自View,如果是继承自系统已有的TextView,Button,已经给你计算好了宽高。
 *    3）onDraw 用于绘制自己的显示
 *    4）onTouch()用于与用户交互
 *
 * 自定义ViewGroup的套路： 顺序：onMeasure->onLayout->onDraw
 *    1）自定义属性，获取自定义属性， 这一步很少做
 *    2）onMeasure方法，for循环测量子View,根据子View的宽高来计算自己的宽高。
 *    3）onLayout() 用于摆放子View, 前提是不是GONE的情况
 *    4）onDraw() 一般不需要，默认情况下是不会调用的，如果你要绘制需要实现dispatchDraw()方法。
 *    5）在很多情况下不会继承自ViewGroup, 往往是继承系统已有的ViewGroup, 如ViewPager,ScrollView,RelativeLayout.
 *
 *
 *
 *
 * View的Touch事件分发：
 *    1）OnTouchListener onTouch OnClickListener 三个都有的情况下，前提是OnTouchListener返回false
 *      OnTouchListener.DOWN->OnTouch.DOWN->OnTouchListener.MOVE->OnTouch.MOVE->OnTouchListener.UP->OnTouch.UP->OnClickListener
 *    2)OnTouchListener onTouch OnClickListener 三个都有的情况下，前提是OnTouchListener返回true
 *      OnTouchListener.DOWN->OnTouchListener.MOVE-OnTouchListener.UP
 *    3)OnTouch OnClickListener 有这个两个的情况下，前提是OnTouch返回true
 *      OnTouch.Down->OnTouch.MOVE->OnTouch.UP    不会执行OnClick
 *    4)dispatchTouchEvent 返回true
 *      不会走OnTouchListener OnTouch OnClickListener中的任何函数。
 *    5）dispatchTouchEvent或者上面的其它三个函数，改成这样：super.dispatchTouchEvent(event); return true;
 *       效果可以自己测试一下。
 *
 *
 *
 * View与Touch相关的两个非常重要的方法：
 *    1）dispatchTouchEvent 事件分发。 其中onClick会在up事件中调用
 *    2）onTouchEvent方法（一般都会被我们复写）
 *    3）onInterceptTouchEvent() 事件拦截方法
 *    4）onFinishInflate() xml解析完毕
 *
 *
 * 系统封装的手势类： new GestureDetector()， 构造函数里面的实现类有两种：
 *   new GestureDetector.OnGestureListener() 必须实现下面的所有方法
 *   new GestureDetector.SimpleOnGestureListener() 所有的方法都有默认的空实现，只需要实现需要的方法就行。
 *      onFling() 快速滑动
 *      onLongProess() 长按
 *      onScroll() 滚动
 *      onSingleTapUp() 短按弹起
 *      onShowPress() 短按
 *      onDown() 按下
 *
 *
 *
 *
 *  加阴影一般用代码addView加。
 *
 *  滑动冲突：
 *    getParent().getParent().requestDisallowInterceptTouchEvent( false );
 *
 *
 *
 *  网上自定义的UI合集：
 *    https://www.jianshu.com/p/07587fc17f11
 *    https://blog.csdn.net/sinat_33585352/article/details/88825720#%E6%8A%BD%E5%B1%89%E8%8F%9C%E5%8D%95
 *
 *
 *
 *  material design的UI涉及有如下：
 *
 *    1）NavigationView  左侧很长的菜单栏
 *    2) CoordinatorLayout 一般和behavior结合， 上面菜单下拉显示， 上拉隐藏。 这个功能很常用。 CoordinatorLayout用于协调各个子控件。
 *    3）AppBarLayout 标题栏：可以结合CoordinatorLayout、AppbarLayout、NestedScrollView实现很好的效果
 *    4）CollapsingToolbarLayout 可以折叠的Toolbar
 *    5）NestedScrollView 支持嵌套滑动的ScrollView
 *    6）TabLayout  官方的tab切换
 *    9）FloatingActionButton  悬浮按钮
 *    10）SnackBar 可以说是Toast的升级版，不仅有显示信息的功能，还可以添加一个Action，实现点击功能，可以右滑删除。默认显示底部充满
 *    11）SwipeRefreshLayout 下拉刷新，上拉加载更多
 *    12）RecyclerView 平时经常用
 *    13）CardView  四周阴影效果、四周圆角效果
 *    14）TextInputLayout  主要是作为 EditText 的容器，从而为 EditText 生成一个浮动的 Label，当用户点击 EditText 的时候，EditText 中的 hint 字符串会自动移到 EditText 的左上角
 *    15）BottomSheetDialog  底部弹出对话框
 *    16）SharedElementTransitions  Activity间的转场动画
 *    17）BottomNavigationView 底部导航栏，比如微信底部导航，支持角标
 *    18）ConstraintLayout  常用的约束布局
 *    19）Chip、ChipGroup、ChipDrawable 流式布局标签，标签中带的选中颜色，图标，删除图标
 *    20）BottomAppBar： 底部菜单栏
 *    21) MaterialButton: 给button加背景、图标、圆角、描边、文字描边、文字按钮、圆形按钮、
 *    22）Adaptive icon: 大概意思就是，之前谷歌设计是支持异形icon的，也就是应用爱圆的，方形的乱七八糟的形状都随你们，但是后来发现这样没有一个规范，就显得很丑。
 *       所以从8.0就设计了一套将icon分为前景和背景的方式拼接，这样还可以实现很好的icon效果android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round"
 *    23）App shortcuts： 在App icon上长按能弹出一个功能列表，用户可以快速使用一些功能
 *
 *
 * 动画：
 *   帧动画：一张一张图片不断轮训播放
 *   补间动画：像位移、缩放、透明度
 *   属性动画：
 *
 *
 *
 *   属性动画中translationY字符串是怎么获得的?
 *   view.setTranslationY(); 复制出translationY字符串就可以了
 *
 *
 * */
public class MainActivity extends AppCompatActivity {

    private ShapeView shapeView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //new A1TextView(this);

        final QQStepView qqStepView = findViewById(R.id.qq_step_view);
        final CycleProgressBar cycleProgressBar = findViewById(R.id.cycleProgressBar);
        shapeView = findViewById(R.id.shapeView);

        qqStepView.setmStepMax(4000);
        cycleProgressBar.setmStepMax(4000);
        //属性动画, 1秒钟，从0变化到3000
        ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 3000);
        valueAnimator.setDuration(1000);
        valueAnimator.setInterpolator(new DecelerateInterpolator()); //添加插值器，先快后慢
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float currentStep = (float)valueAnimator.getAnimatedValue();
                qqStepView.setmCurrentStep((int)currentStep);
                cycleProgressBar.setmCurrentStep((int)currentStep);
            }
        });
        valueAnimator.start();

        changeShapView();
    }

    private void changeShapView() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            shapeView.exchange();
                        }
                    });
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    public void onClickToLetterSideBar(View view) {
        startActivity(new Intent(this, LetterSideBarActivity.class));
    }

    public void onClickToTagLayout(View view) {
        startActivity(new Intent(this, TagLayoutActivity.class));
    }

    public void onClickToMessageBubble(View view) {
        startActivity(new Intent(this, MessageBubbleActivity.class));
    }
}
